<template>
    <div class="default-main">
        <el-row v-loading="state.loading" :gutter="20">
            <el-col class="xs-mb-20" :xs="24" :sm="16">
                <el-form v-if="!state.loading" ref="formRef" :model="state.form" :rules="state.rules" :label-position="'top'" :key="state.formKey">
                    <el-tabs v-model="state.activeTab" type="border-card" :before-leave="onBeforeLeave">
                        <el-tab-pane class="config-tab-pane" v-for="(group, key) in state.config" :key="key" :name="key" :label="group.title">
                            <div class="config-form-item" v-for="(item, idx) in group.list" :key="idx">
                                <template v-if="item.group == state.activeTab">
                                    <!-- 富文本在dialog内全屏编辑器时必须拥有很高的z-index，此处选择单独为editor设定较小的z-index -->
                                    <FormItem
                                        v-if="item.type == 'editor'"
                                        :label="item.title"
                                        :type="item.type"
                                        @keyup.enter.stop=""
                                        @keyup.ctrl.enter="onSubmit()"
                                        v-model="state.form[item.name]"
                                        :attr="{ prop: item.name, ...item.extend }"
                                        :input-attr="{
                                            style: {
                                                zIndex: 99,
                                            },
                                            ...item.input_extend,
                                        }"
                                        :data="{}"
                                        :key="'editor-' + item.id"
                                        :tip="item.tip.replace(/\{\}/g, state.form[item.name])"
                                        :blockHelp="item.extend.blockHelp?.toString().replace(/\{\}/g, state.form[item.name])"
                                    />
                                    <FormItem
                                        v-else-if="item.type == 'textarea'"
                                        :label="item.title"
                                        :type="item.type"
                                        @keyup.enter.stop=""
                                        @keyup.ctrl.enter="onSubmit()"
                                        v-model="state.form[item.name]"
                                        :attr="{ prop: item.name, ...item.extend }"
                                        :input-attr="{ rows: 3, ...item.input_extend }"
                                        :data="{}"
                                        :key="'textarea-' + item.id"
                                        :tip="item.tip.replace(/\{\}/g, state.form[item.name])"
                                        :blockHelp="item.extend.blockHelp?.toString().replace(/\{\}/g, state.form[item.name])"
                                    />
                                    <FormItem
                                        v-else-if="item.type == 'array'"
                                        :label="item.title"
                                        :type="item.type"
                                        v-model="state.form[item.name]"
                                        :attr="{ prop: item.name, ...item.extend }"
                                        :input-attr="{ ...item.input_extend }"
                                        :key="'array-' + item.id"
                                        :tip="item.tip.replace(/\{\}/g, state.form[item.name])"
                                        :blockHelp="item.extend.blockHelp?.toString().replace(/\{\}/g, state.form[item.name])"
                                    />
                                    <InputNumber
                                        v-else-if="item.type == 'number'"
                                        :label="item.title"
                                        :type="item.type"
                                        :prop="item.name"
                                        v-model="state.form[item.name]"
                                        :attr="{ prop: item.name, ...item.extend }"
                                        :input-attr="{ ...item.input_extend }"
                                        :key="'number-' + item.id"
                                        :tip="item.tip.replace(/\{\}/g, state.form[item.name])"
                                        :blockHelp="item.extend.blockHelp?.toString().replace(/\{\}/g, state.form[item.name])"
                                    />
                                    <el-form-item v-else-if="item.type == 'password'" :label="item.title" :prop="item.name">
                                        <template #label>
                                            <span>{{ item.title }}</span>
                                            <span class="tip">
                                                <el-tooltip v-if="item.tip" effect="dark" :content="item.tip" placement="top">
                                                    <i class="fa fa-question-circle"></i>
                                                </el-tooltip>
                                            </span>
                                        </template>
                                        <el-input v-model="state.form[item.name]" :disabled="state.form[item.name] == '**********'">
                                            <template
                                                #append
                                                v-if="(auth('getSensitiveFieldValue') || auth('save')) && state.form[item.name] == '**********'"
                                            >
                                                <el-popconfirm title="正在查看敏感内容,是否继续？" width="250" @confirm="getFieldValue(item.name)">
                                                    <template #reference>
                                                        <el-button>查看</el-button>
                                                    </template>
                                                </el-popconfirm>
                                            </template>
                                        </el-input>
                                        <div class="help-block" v-if="item.extend.blockHelp">
                                            {{ item.extend.blockHelp?.toString().replace(/\{\}/g, state.form[item.name]) }}
                                        </div>
                                    </el-form-item>
                                    <FormItem
                                        v-else
                                        :label="item.title"
                                        :type="item.type"
                                        v-model="state.form[item.name]"
                                        :attr="{ prop: item.name, ...item.extend }"
                                        :input-attr="{ ...item.input_extend }"
                                        :data="{
                                            content: item.content ? item.content : {},
                                            childrenAttr: { ...item.input_extend },
                                        }"
                                        :key="'other-' + item.id"
                                        :tip="item.tip.replace(/\{\}/g, state.form[item.name])"
                                        :blockHelp="item.extend.blockHelp?.toString().replace(/\{\}/g, state.form[item.name])"
                                    />
                                    <!-- 编辑与删除只能超管操作 -->
                                    <div class="form-item-operate" v-if="adminInfo.super">
                                        <div class="edit-config-form-item">
                                            <Icon class="edit-icon" name="el-icon-Edit" size="15" @click="openEditForm(item.id)" />
                                        </div>
                                        <div class="del-config-form-item" v-if="adminInfo.super">
                                            <el-popconfirm
                                                placement="right-end"
                                                width="300"
                                                @confirm="onDelConfig(item)"
                                                :title="'确定要删除配置项【' + item.title + '】吗?'"
                                            >
                                                <template #reference>
                                                    <Icon class="close-icon" size="15" name="el-icon-Delete" />
                                                </template>
                                            </el-popconfirm>
                                        </div>
                                    </div>
                                </template>
                            </div>
                            <div style="padding-top: 30px">
                                <el-button v-auth="'save'" type="primary" @click="onSubmit()">保存</el-button>
                            </div>
                        </el-tab-pane>
                        <div v-if="adminInfo.super">
                            <el-tab-pane label="配置分组" name="config_group">
                                <FormItem
                                    :type="'array'"
                                    v-model="state.configGroups"
                                    :input-attr="{
                                        keyTitle: '分组变量名',
                                        valueTitle: '分组标题',
                                    }"
                                />
                                <el-button type="primary" @click="onSubmitConfigGroup()">保存</el-button>
                            </el-tab-pane>
                            <el-tab-pane name="add_config" class="config-tab-pane config-tab-pane-add" label="添加配置项"></el-tab-pane>
                        </div>
                    </el-tabs>
                </el-form>
            </el-col>
        </el-row>

        <AddForm
            v-if="!state.loading"
            v-model="state.showAddForm"
            :config-group="state.configGroup"
            :config="state.config"
            :url="state.url"
            @update:config="updateConfig"
        />

        <EditForm
            v-if="!state.loading"
            v-model="state.showEditForm"
            :config-group="state.configGroup"
            :config="state.config"
            :url="state.url"
            @update:config="updateConfig"
            :config-data="state.configData"
        />
    </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import FormItem from '/@/components/formItem/index.vue'
import { FormInstance, FormItemRule } from 'element-plus'
import AddForm from './add.vue'
import EditForm from './edit.vue'
import { buildValidatorData, buildValidatorParams } from '/@/utils/validate'
import { uuid } from '/@/utils/random'
import { index, postData, delData, getData, getSensitiveFieldValue } from './setting'
import { useAdminInfo } from '/@/stores/adminInfo'
import InputNumber from '../form/inputNumber.vue'
import { auth } from '/@/utils/common'
import { adminBaseRoutePath } from '/@/router/static/adminBase'

const adminInfo = useAdminInfo()

interface Prop {
    url: string
}
const props = withDefaults(defineProps<Prop>(), {})

defineOptions({
    name: adminBaseRoutePath + '/setting',
})

// 查看敏感字段值
const getFieldValue = (name: string) => {
    getSensitiveFieldValue(state.url, 'get_sensitive_field_value', name).then((res) => {
        state.form[name] = res.data
        state.sensitiveFieldValues[name] = state.form[name]
    })
}

const formRef = ref<FormInstance>()

const state: {
    loading: boolean
    config: anyObj
    remark: string
    configGroup: anyObj
    activeTab: string
    showAddForm: boolean
    showEditForm: boolean
    rules: Partial<Record<string, FormItemRule[]>>
    form: anyObj
    quickEntrance: anyObj
    formKey: string
    url: string
    configGroups: { key: string; value: string }[]
    configData: anyObj
    sensitiveFieldValues: anyObj
} = reactive({
    loading: true,
    config: [],
    remark: '',
    configGroup: {},
    activeTab: 'config_group',
    showAddForm: false,
    showEditForm: false,
    rules: {},
    form: {},
    quickEntrance: {},
    formKey: uuid(),
    url: props.url,
    configGroups: [],
    configData: {},
    sensitiveFieldValues: {},
})

const getIndex = () => {
    index(state.url)
        .then((res) => {
            state.config = res.data.list
            state.remark = res.data.remark
            state.configGroup = res.data.configGroup
            state.quickEntrance = res.data.quickEntrance
            state.loading = false
            state.sensitiveFieldValues = {}
            for (const key in state.configGroup) {
                state.activeTab = key
                if (state.configGroups.length == 0) {
                    state.configGroups.push({
                        key: key,
                        value: state.configGroup[key],
                    })
                }
                break
            }
            let formNames: anyObj = {}
            let rules: Partial<Record<string, FormItemRule[]>> = {}
            for (const key in state.config) {
                for (const lKey in state.config[key].list) {
                    formNames[state.config[key].list[lKey].name] =
                        state.config[key].list[lKey].type == 'number'
                            ? parseFloat(state.config[key].list[lKey].value)
                            : state.config[key].list[lKey].value
                    if (state.config[key].list[lKey].rule) {
                        let ruleStr = state.config[key].list[lKey].rule.split(',')
                        let ruleArr: anyObj = []
                        ruleStr.forEach((item: string) => {
                            ruleArr.push(
                                buildValidatorData({ name: item as buildValidatorParams['name'], title: state.config[key].list[lKey].title })
                            )
                        })
                        rules = Object.assign(rules, {
                            [state.config[key].list[lKey].name]: ruleArr,
                        })
                    }
                }
            }
            state.form = formNames
            state.rules = rules
            state.formKey = uuid()
            state.configGroups = Object.entries(state.configGroup).map(([key, value]) => {
                return {
                    key: key,
                    value: value,
                }
            })
        })
        .catch(() => {
            state.loading = false
        })
}

const onBeforeLeave = (newTabName: string | number) => {
    if (newTabName == 'add_config') {
        state.showAddForm = true
        return false
    }
}

const onSubmit = () => {
    if (!formRef.value) return
    formRef.value.validate((valid) => {
        if (valid) {
            // 只提交当前tab的表单数据
            const formData: anyObj = {}
            for (const key in state.config) {
                if (key != state.activeTab) {
                    continue
                }
                for (const lKey in state.config[key].list) {
                    formData[state.config[key].list[lKey].name] = state.form[state.config[key].list[lKey].name] ?? ''
                }
            }
            if (!formData) return
            postData(state.url, 'save', formData).then(() => {
                getIndex()
            })
        }
    })
}

const onSubmitConfigGroup = () => {
    const params = {
        value: state.configGroups,
        extend: [],
        type: 'array',
        inputExtend: [],
    }
    postData(state.url, 'edit_group', params).then((res) => {
        state.config = res.data.list
        state.configGroup = res.data.configGroup
    })
}

const onDelConfig = (config: anyObj) => {
    delData(state.url, [config.id]).then(() => {
        getIndex()
    })
}

const updateConfig = () => {
    getIndex()
}

const openEditForm = (id: string) => {
    getData(state.url, 'edit', id).then((res) => {
        state.configData = res.data
        state.showEditForm = true
    })
}

onMounted(async () => {
    if (state.url) {
        getIndex()
    } else {
        state.loading = false
        throw new Error('缺少配置项请求url')
    }
})
</script>

<style scoped lang="scss">
.send-test-mail {
    padding-bottom: 20px;
}
.el-tabs--border-card {
    border: none;
    box-shadow: var(--el-box-shadow-light);
    border-radius: var(--el-border-radius-base);
}
.el-tabs--border-card :deep(.el-tabs__header) {
    background-color: var(--ba-bg-color);
    border-bottom: none;
    border-top-left-radius: var(--el-border-radius-base);
    border-top-right-radius: var(--el-border-radius-base);
}
.el-tabs--border-card :deep(.el-tabs__item.is-active) {
    border: 1px solid transparent;
}
.el-tabs--border-card :deep(.el-tabs__nav-wrap) {
    border-top-left-radius: var(--el-border-radius-base);
    border-top-right-radius: var(--el-border-radius-base);
}
.el-card :deep(.el-card__header) {
    height: 40px;
    padding: 0;
    line-height: 40px;
    border: none;
    padding-left: 20px;
    background-color: var(--ba-bg-color);
}
.config-tab-pane {
    padding: 5px;
}
.config-tab-pane-add {
    width: 80%;
}
.config-form-item {
    display: flex;
    align-items: flex-start;
    .el-form-item {
        flex: 13;
    }
    .config-form-item-name {
        font-size: 14px;
        opacity: 0;
        flex: 2;
        color: var(--el-text-color-disabled);
        padding-left: 10px;
    }
    .form-item-operate {
        display: flex;
        height: 0px;
    }
    .del-config-form-item {
        cursor: pointer;
        flex: 1;
        padding-right: 10px;
    }
    .edit-config-form-item {
        cursor: pointer;
        flex: 1;
        padding-right: 10px;
        padding-bottom: 10px;
    }
}
.config_quick_entrance {
    margin-left: 10px;
    margin-bottom: 10px;
}
@media screen and (max-width: 768px) {
    .xs-mb-20 {
        margin-bottom: 20px;
    }
}
.help-block {
    width: 100%;
    margin-top: 5px;
    font-size: 13px;
    line-height: 16px;
    color: #999;
}
.tip {
    padding-left: 6px;
    color: var(--el-text-color-secondary);
    i {
        cursor: pointer;
    }
}
</style>
